/*
 * Copyright 2010-2012 Susanta Tewari. <freecode4susant@users.sourceforge.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package coalescent.cef.pui.pob;

import cef.pui.pob.*;
import coalescent.data.K69Data;
import coalescent.data.KC64Data;
import coalescent.data.meta.MetaInf_AC;
import coalescent.data.meta.MetaInf_K69Data;
import coalescent.data.meta.MetaInf_Mngr;
import coalescent.model.K69;
import coalescent.model.KC64;
import coalescent.model.PopGenModel;
import coalescent.phylogeny.PhylogenyAlgo;
import coalescent.provider.Providers;
import coalescent.recursion.RecursionListener;
import coalescent.statistic.AC;
import coalescent.statistic.K69_AC;
import coalescent.statistic.KC64_AC;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import commons.core.*;
import commons.util.ConverterUtil;
import commons.util.base.Converter;
import org.netbeans.api.annotations.common.NullAllowed;

import java.io.File;
import java.util.List;
import java.util.Properties;

/**
 * Builds various value objects in coalescent-core using string based key-value pairs. The key-value pairs are provided
 * via a {@link Properties} object.
 *
 * @author Susanta Tewari
 * @version 1.4
 * @history Created on Dec 8, 2010.
 * @since 1.3
 */
public class Builders_Coa {

    /**
     * Builder for value type {@code PopGenModel}. The available properties are:
     * <ul>
     * <li>{@code coalescent.builder.PopGenModel.delegate = coalescent.cef.pui.pob.Builders_Coa$Model_KC64 | coalescent.cef.pui.pob.Builders_Coa$Model_K69}</li>
     * </ul>
     *
     *
     * @param props properties object containing builder properties
     * @param prefix
     * @return a new builder instance for interface {@code PopGenModel}
     */
    public static Builder<PopGenModel> of_Model_PopGen(final Properties props, String prefix) {

        if (prefix == null) prefix = "coalescent.builder.PopGenModel";

        return new cef.pui.pob.Builders.InterfaceBuilder<>(prefix, props);
    }

    /**
     * Properties:
     * <ul>
     *     <li>{@code coalescent.builder.KC64.theta = valid double string as specified in } {@link Double#parseDouble(java.lang.String)}</li>
     * </ul>
     *
     *
     * @param props properties object containing builder properties
     * @param prefix
     * @return a new builder instance for {@code KC64}
     */
    public static Builder<KC64> of_Model_KC64(final Properties props, String prefix) {

        if (prefix == null) prefix = "coalescent.builder.KC64";

        return new StringBasedBuilder<KC64>(prefix, props, "theta") {

            @Override
            protected KC64 newInstance(final String propValue) {
                return new KC64(new Double(propValue));
            }
            @Override
            public String getBuilderString() {
                return "coalescent.cef.pui.pob.Builders_Coa$Model_KC64";
            }
        };
    }

    /**
     * Builder for value type {@code List<KC64>}. The available properties are:
     * <ul>
     *   <li>{@code coalescent.builder.KC64List.theta.min = valid double string as specified in } {@link Double#parseDouble(java.lang.String)}</li>
     *   <li>{@code coalescent.builder.KC64List.theta.max = valid double string as specified in } {@link Double#parseDouble(java.lang.String)}</li>
     *   <li>{@code coalescent.builder.KC64List.theta.increment = valid double string as specified in } {@link Double#parseDouble(java.lang.String)}</li>
     * </ul>
     *
     *
     * @param props properties object containing builder properties
     * @param prefix
     * @return a new builder instance for {@code List<KC64>}
     */
    public static Builder<List<KC64>> of_Models_KC64(final Properties props, String prefix) {

        if (prefix == null) prefix = "coalescent.builder.KC64List.theta";

        final Builder<List<K69>> k69List_b = of_Models_K69(props, null);

        k69List_b.setPrefix(prefix);

        return new Builder<List<KC64>>(prefix, props) {

            @Override
            protected List<KC64> buildFromProps() throws BuilderException {

                return ImmutableList.copyOf(ConverterUtil.convert(k69List_b.build(),
                        new Converter<K69, KC64>() {

                    @Override
                    public KC64 convert(final K69 input) {
                        return new KC64(input.getMutationRate());
                    }

                }));
            }
            @Override
            public String getBuilderString() {
                return "NotYetImplemented";
            }
        };
    }

    /**
     * Builder for value type {@code AC}. The available properties are:
     * <ul>
     * <li>{@code coalescent.builder.AC.delegate = coalescent.cef.pui.pob.Builders_Coa$AC_KC64 | coalescent.cef.pui.pob.Builders_Coa$AC_K69_GT_File}</li>
     * </ul>
     *
     *
     * @param props properties from event implementations
     * @param prefix
     * @return a new builder instance for interface {@code AC}
     */
    public static Builder<AC<?, ?>> of_AC(final Properties props, String prefix) {

        if (prefix == null) prefix = "coalescent.builder.AC";

        return new cef.pui.pob.Builders.InterfaceBuilder<>(prefix, props);
    }

    /**
     * Properties:
     * <ul>
     *     <li>{@code coalescent.builder.KC64Data.theta = valid double string as specified in } {@link Double#parseDouble(java.lang.String)}</li>
     *     <li>{@code coalescent.builder.KC64Data.an = valid values are of the format f1^t1_f2^t2... where fi and ti are positive and represent the frequency domain, and the alleles on that frequency domain, respectively}</li>
     * </ul>
     *
     *
     * @param props properties object containing builder properties
     * @param prefix
     * @return a new builder instance for {@code KC64Data.DEFAULT}
     */
    public static StringBasedBuilder<KC64Data.DEFAULT> of_Data_KC64_Default(final Properties props,
            String prefix) {

        if (prefix == null) prefix = "coalescent.builder.KC64Data";

        final Builder<KC64> kc64Builder = of_Model_KC64(props, null);

        kc64Builder.setPrefix(prefix);

        return new StringBasedBuilder<KC64Data.DEFAULT>(prefix, props, "an") {

            @Override
            protected KC64Data.DEFAULT newInstance(final String propValue) {

                final KC64 kc64 = kc64Builder.build();

                return KC64Data.ofCannonicalForm(kc64, propValue);
            }
            @Override
            public String getBuilderString() {
                return "NotYetImplemented";
            }
        };
    }

    /**
     * Builder for value type {@code LikelihoodComputer<KC64Data.DEFAULT>}. The available properties are:
     * <ul>
     *     <li>{@code coalescent.builder.KC64LHood.implCode = exact-recursion |esf}</li>
     * </ul>
     *
     *
     * @param props builder properties
     * @param prefix
     * @return a new builder instance for {@code LikelihoodComputer<KC64Data.DEFAULT>}
     */
    public static Builder<LikelihoodComputer<KC64Data.DEFAULT>> of_LHoodComputer_KC64(
            final Properties props, String prefix) {

        if (prefix == null) prefix = "coalescent.builder.KC64LHood";

        return new ICBasedBuilder<LikelihoodComputer<KC64Data.DEFAULT>,
                                  Providers.KC64LHoodProvider>(prefix, props) {

            @Override
            protected Class<Providers.KC64LHoodProvider> getDefaultProviderClass() {
                return Providers.KC64LHoodProvider.class;
            }
            @Override
            public String getBuilderString() {
                return "NotYetImplemented";
            }
        };
    }

    /**
     * Properties:
     * <ul>
     *     <li>{@code coalescent.builder.KC64MultiLHood.implCode = exact-recursion-multi | esf-multi}</li>
     * </ul>
     *
     *
     * @param props builder properties
     * @param prefix
     * @return a new builder instance for {@code MultiLHoodComputer<KC64, KC64Data.DEFAULT, KC64Data.DEFAULT>}
     */
    public static Builder<MultiLHoodComputer<KC64, KC64Data.DEFAULT,
            KC64Data.DEFAULT>> of_MultiLHoodComputer_KC64(final Properties props, String prefix) {

        if (prefix == null) prefix = "coalescent.builder.KC64MultiLHood";

        return new ICBasedBuilder<MultiLHoodComputer<KC64, KC64Data.DEFAULT, KC64Data.DEFAULT>,
                                  Providers.KC64MultiLHoodProvider>(prefix, props) {

            @Override
            protected Class<Providers.KC64MultiLHoodProvider> getDefaultProviderClass() {
                return Providers.KC64MultiLHoodProvider.class;
            }
            @Override
            public String getBuilderString() {
                return "NotYetImplemented";
            }
        };
    }

    /**
     * Builder for value type {@code K69}. The available properties are:
     * <ul>
     *   <li>{@code coalescent.builder.K69.theta = valid double string as specified in } {@link Double#parseDouble(java.lang.String)}</li>
     * </ul>
     *
     *
     * @param props properties object containing builder properties
     * @param prefix
     * @return a new builder instance for {@code K69}
     */
    public static Builder<K69> of_Model_K69(final Properties props, String prefix) {

        if (prefix == null) prefix = "coalescent.builder.K69";

        return new Builder<K69>(prefix, props) {

            @Override
            protected K69 buildFromProps() throws BuilderException {

                final Builder<KC64> kc64Builder = of_Model_KC64(super.props, null);

                kc64Builder.setPrefix(getPrefix());

                return new K69(kc64Builder.build().getMutationRate());
            }
            @Override
            public String getBuilderString() {
                return "coalescent.cef.pui.pob.Builders_Coa$Model_K69";
            }
        };
    }

    /**
     * Builder for value type {@code Generator.MODEL<List<Double>,K69>}. The properties are:
     * <ul>
     *     <li>{@code coalescent.builder.K69GeneratorProvider.implCode = k69:1}</li>
     * </ul>
     *
     *
     * @param props builder properties
     * @param prefix
     * @return a new builder instance for {@code Generator.MODEL<List<Double>,K69>}
     */
    public static Builder<Generator.MODEL<List<Double>,
            K69>> of_Generator_Model_K69(final Properties props, String prefix) {

        if (prefix == null) prefix = "coalescent.builder.K69GeneratorProvider";

        return new ICBasedBuilder<Generator.MODEL<List<Double>, K69>,
                                  Providers.K69GeneratorProvider>(prefix, props) {

            @Override
            protected Class<Providers.K69GeneratorProvider> getDefaultProviderClass() {
                return Providers.K69GeneratorProvider.class;
            }
            @Override
            public String getBuilderString() {
                return "NotYetImplemented";
            }
        };
    }

    /**
     * Builder for value type {@code List<K69>}. The available properties are:
     * <ul>
     *   <li>{@code coalescent.builder.K69List.theta.min = valid double string as specified in } {@link Double#parseDouble(java.lang.String)}</li>
     *   <li>{@code coalescent.builder.K69List.theta.max = valid double string as specified in } {@link Double#parseDouble(java.lang.String)}</li>
     *   <li>{@code coalescent.builder.K69List.theta.increment = valid double string as specified in } {@link Double#parseDouble(java.lang.String)}</li>
     * </ul>
     *
     *
     * @param props properties object containing builder properties
     * @param prefix
     * @return a new builder instance for {@code List<K69>}
     */
    public static Builder<List<K69>> of_Models_K69(final Properties props, String prefix) {

        if (prefix == null) prefix = "coalescent.builder.K69List.theta";

        return Builder.of_delegate(Builders.of_List_Double_byRange(props, prefix),
                                   new Converter<List<Double>, List<K69>>() {

            @Override
            public List<K69> convert(List<Double> input) {

                return Lists.newArrayList(Collections2.transform(input,
                        new Function<Double, K69>() {

                    @Override
                    public K69 apply(Double input) {
                        return new K69(input);
                    }

                }));
            }

        });
    }

    /**
     * Builder for value type {@code Simulator.DATA<TAB08, TAB08Data>}. The properties are:
     * <ul>
     *     <li>{@code coalescent.builder.K69DataSimulator.implCode = k69data-ms}</li>
     * </ul>
     *
     *
     * @param props builder properties
     * @param prefix
     * @return a new builder instance for {@code Simulator.DATA<K69, K69Data>}
     */
    public static Builder<Simulator.DATA<K69,
            K69Data>> of_Simulator_Data_K69(final Properties props, String prefix) {

        if (prefix == null) prefix = "coalescent.builder.K69DataSimulator";

        return new ICBasedBuilder<Simulator.DATA<K69, K69Data>,
                                  Providers.K69DataSimulatorProvider>(prefix, props) {

            @Override
            protected Class<Providers.K69DataSimulatorProvider> getDefaultProviderClass() {
                return Providers.K69DataSimulatorProvider.class;
            }
            @Override
            public String getBuilderString() {
                return "NotYetImplemented";
            }
        };
    }

    /**
     * Builder for value type {@code K69Data}. The available properties are:
     * <ul>
     *  <li>{@code coalescent.builder.K69Data.url = k69data:xml//URL }</li>
     * </ul>
     *
     *
     * @param props properties object containing builder properties
     * @param prefix
     * @return a new builder instance for {@code K69Data}
     */
    public static URLBasedBuilder<K69Data> of_Data_K69_File(final Properties props,
            @NullAllowed String prefix) {

        if (prefix == null) prefix = "coalescent.builder.K69Data";

        return new URLBasedBuilder<K69Data>(prefix, props) {

            @Override
            protected Class<Providers.K69DataProviderFileBased> getDefaultProviderClass() {
                return Providers.K69DataProviderFileBased.class;
            }
            @Override
            public String getBuilderString() {
                return "coalescent.cef.pui.pob.Builders_Coa$Data_K69_File";
            }
        };
    }

    /**
     * Builder with same properties as {@link #of_Data_K69_File(java.util.Properties, String)}.
     * Detects a PLayout_NodeLabel layout file with the same url as K69Data but with
     * extension 'PLayout' (in lowercase).
     */
    public static Builder<String> getGeneTree_PLayoutPath(final Properties props) {

        final URLBasedBuilder<K69Data> data_b = of_Data_K69_File(props, null);

        return new Builder.Adapter<String>(data_b.getPrefix(), props) {

            @Override
            public String build() throws BuilderException {
                return data_b.getURL() + ".PLayout";
            }
        };
    }

    /**
     * Builder with same properties as {@link #of_Data_K69_File(java.util.Properties, String)}.
     * Detects a {@code MetaInf} with the same url as K69Data but with
     * extension 'MetaInf'.
     */
    public static Builder<MetaInf_Mngr<MetaInf_K69Data>> of_MetaInf_Mngr_K69Data_File(
            final Properties props, @NullAllowed String prefix, String activePfx) {

        final String implCode  = "metainf_k69data:rw_xml";
        final String exTension = ".MetaInf";

        if (prefix == null) prefix = "coalescent.builderRW.MetaInf_K69Data"; //J-

        final URLBasedBuilder<K69Data> data_b = of_Data_K69_File(props, prefix);

        Properties props1 = new Properties();
        props1.setProperty(data_b.getFullURLKey(), implCode + "//" + data_b.getURL() + exTension);//J+


        final URLBasedBuilder_RW<MetaInf_K69Data> metaInf_b =
            new URLBasedBuilder_RW<MetaInf_K69Data>(prefix, props1) {

            @Override
            public String getBuilderString() {
                return "coalescent.cef.pui.pob.Builders_Coa$MetaInfMngr_K69Data_File";
            }
            @Override
            protected Class<? extends commons.provider.Providers
                .FileBasedProvider_RW> getDefaultProviderClass() {
                return Providers.MetaInf_K69Data_Provider_FileBased_RW.class;
            }
            @Override
            public MetaInf_K69Data newInstanceImpl() {
                return new MetaInf_K69Data();
            }
            @Override
            public boolean canBuild() {
                return super.canBuild() && new File(getURL()).exists();
            }
        };

        return new MetaInf_Mngr_Builder<>(props, metaInf_b, prefix, activePfx);
    }

    /**
     * Properties:
     * <ul>
     *  <li>{@code coalescent.MetaInf_AC.delegate =
     *      coalescent.cef.pui.pob.Builders_Coa$MetaInfMngr_K69Data_File}
     *  </li>
     * </ul>
     *
     *
     * @param props properties from event implementations
     * @param prefix
     * @return a new builder instance for interface {@code MetaInf_AC}
     */
    public static Builder<MetaInf_Mngr<MetaInf_AC>> of_MetaInf_Mngr_AC(final Properties props,
            String prefix, String activePfx) {

        if (prefix == null) prefix = "coalescent.MetaInf_AC";

        final Builder_RW<MetaInf_AC> metaInf_b = new Builders.InterfaceBuilder_RW<>(prefix, props);

        return new MetaInf_Mngr_Builder<>(props, metaInf_b, prefix, activePfx);
    }

    /**
     * Properties:
     * <ul>
     *    <li>{@code coalescent.builder.K69Data.url = k69data:xml//URL }<a href="coalescent/cef/pui/pob/doc-files/k69data.xml.txt">file format</a>, must accompany the <a href="coalescent/cef/pui/pob/doc-files/k69data.xsd.txt">schema</a></li>
     *    <li>{@code coalescent.builder.K69Estimator.implCode = watterson}</li>
     * </ul>
     *
     *
     * @param props properties object passed from event implementations
     * @param prefix
     * @return a new builder instance for {@code ModelEstimator<K69, K69Data, K69Data, ?>}
     */
    public static Builder<ModelEstimator<K69, K69Data, K69Data,
            ?>> of_ModelEstimator_K69(final Properties props, String prefix) {

        if (prefix == null) prefix = "coalescent.builder.K69Estimator";

        return new DataBasedBuilder<ModelEstimator<K69, K69Data, K69Data, ?>, K69, K69Data,
                                    coalescent.provider.Providers.K69EstimatorProvider>(prefix,
                                        props) {

            @Override
            protected Builder<K69Data> getDataBuilder() {
                return of_Data_K69_File(super.props, null);
            }
            @Override
            protected Class<coalescent.provider.Providers
                .K69EstimatorProvider> getDefaultProviderClass() {
                return coalescent.provider.Providers.K69EstimatorProvider.class;
            }
            @Override
            public String getBuilderString() {
                return "NotYetImplemented";
            }
        };
    }

    /**
     * Builder for value type {@code LikelihoodComputer<K69Data>}. The available properties are:
     * <ul>
     *     <li>{@code coalescent.builder.K69LHood.implCode = exact-recursion}</li>
     * </ul>
     *
     *
     * @param props builder properties
     * @param prefix
     * @return a new builder instance for {@code LikelihoodComputer<K69Data>}
     */
    public static Builder<LikelihoodComputer<K69Data>> of_LHoodComputer_K69(final Properties props,
            String prefix) {

        if (prefix == null) prefix = "coalescent.builder.K69LHood";

        return new ICBasedBuilder<LikelihoodComputer<K69Data>, Providers.K69LHoodProvider>(prefix,
                                  props) {

            @Override
            protected Class<Providers.K69LHoodProvider> getDefaultProviderClass() {
                return Providers.K69LHoodProvider.class;
            }
            @Override
            public String getBuilderString() {
                return "NotYetImplemented";
            }
        };
    }

    /**
     * Properties:
     * <ul>
     *     <li>{@code coalescent.builder.K69MultiLHood.implCode = exact-recursion-multi}</li>
     * </ul>
     *
     *
     * @param props builder properties
     * @param prefix
     * @return a new builder instance for {@code MultiLHoodComputer<K69, K69Data, K69Data>}
     */
    public static Builder<MultiLHoodComputer<K69, K69Data,
            K69Data>> of_MultiLHoodComputer_K69(final Properties props, String prefix) {

        if (prefix == null) prefix = "coalescent.builder.K69MultiLHood";

        return new ICBasedBuilder<MultiLHoodComputer<K69, K69Data, K69Data>,
                                  Providers.K69MultiLHoodProvider>(prefix, props) {

            @Override
            protected Class<Providers.K69MultiLHoodProvider> getDefaultProviderClass() {
                return Providers.K69MultiLHoodProvider.class;
            }
            @Override
            public String getBuilderString() {
                return "NotYetImplemented";
            }
        };
    }

    /**
     * Builder for value type {@code GeneTree}. The available properties are:
     * <ul>
     * <li>{@code coalescent.builder.GeneTree.url = k69data:xml//URL }</li>
     * </ul>
     *
     *
     * @param props properties object containing builder properties
     * @param prefix
     * @return a new builder instance for {@code GeneTree}
     */
    public static Builder<K69_AC> of_AC_K69_GT_File(final Properties props, String prefix) {

        if (prefix == null) prefix = "coalescent.builder.GeneTree";

        return new Builder<K69_AC>(prefix, props) {

            @Override
            protected K69_AC buildFromProps() throws BuilderException {

                final Builder<K69Data> k69DataBuilder = of_Data_K69_File(super.props, null);

                k69DataBuilder.setPrefix(getPrefix());

                return new K69_AC(k69DataBuilder.build());
            }
            @Override
            public String getBuilderString() {
                return "NotYetImplemented";
            }
        };
    }

    /**
     * Builder for value type {@code An}. The available properties are:
     * <ul>
     * <li>{@code coalescent.builder.An.an = valid values are of the format f1^t1_f2^t2... where fi and ti are positive and represent the frequency domain, and the alleles on that frequency domain, respectively}</li>
     * </ul>
     *
     *
     * @param props properties object containing builder properties
     * @param prefix
     * @return a new builder instance for {@code An}
     */
    public static Builder<KC64_AC> of_AC_KC64(final Properties props, String prefix) {

        if (prefix == null) prefix = "coalescent.builder.An";

        return new StringBasedBuilder<KC64_AC>(prefix, props, "an") {

            @Override
            protected KC64_AC newInstance(final String propValue) {
                return new KC64_AC(new KC64(1.0), propValue);
            }
            @Override
            public String getBuilderString() {
                return "coalescent.cef.pui.pob.Builders_Coa$AC_KC64";
            }
        };
    }

    /**
     * Builder for value type {@code An}. The available properties are:
     * <ul>
     *     <li>{@code coalescent.builder.KC64Data.url = k69data:xml//URL }<a href="coalescent/cef/pui/pob/doc-files/k69data.xml.txt">file format</a>, must accompany the <a href="coalescent/cef/pui/pob/doc-files/k69data.xsd.txt">schema</a></li>
     * </ul>
     *
     *
     * @param props properties object containing builder properties
     * @param prefix
     * @return a new builder instance for {@code An}
     */
    public static Builder<KC64Data.DEFAULT> of_Data_KC64_K69Data(final Properties props,
            String prefix) {

        if (prefix == null) prefix = "coalescent.builder.KC64Data";

        return new Builder<KC64Data.DEFAULT>(prefix, props) {

            @Override
            protected KC64Data.DEFAULT buildFromProps() throws BuilderException {

                final Builder<K69Data> k69DataBuilder = of_Data_K69_File(super.props, null);

                k69DataBuilder.setPrefix(getPrefix());

                final K69Data k69Data = k69DataBuilder.build();

                return new KC64Data.DEFAULT(k69Data.getModel(), k69Data.getAlleleFreqMap());
            }
            @Override
            public String getBuilderString() {
                return "coalescent.cef.pui.pob.Builders_Coa$Data_Data_KC64_K69Data";
            }
        };
    }

    /**
     * Builder for value type {@code PhylogenyAlgo}. The available properties are:
     * <ul>
     * <li>{@code coalescent.builder.PhylogenyAlgo.algorithm = valid values are GUSFIELD and FOURGAMETES}</li>
     * </ul>
     *
     *
     * @param props properties object containing builder properties
     * @param prefix
     * @return a new builder instance for {@code PhylogenyAlgo}
     */
    public static Builder<PhylogenyAlgo> of_PhylogenyAlgo(final Properties props, String prefix) {

        if (prefix == null) prefix = "coalescent.builder.PhylogenyAlgo";

        return new StringBasedBuilder<PhylogenyAlgo>(prefix, props, "algorithm") {

            @Override
            protected PhylogenyAlgo newInstance(final String propValue) {
                return PhylogenyAlgo.valueOf(propValue);
            }
            @Override
            public String getBuilderString() {
                return "NotYetImplemented";
            }
        };
    }

    /**
     * Builder for value type {@code List<RecursionListener>}. The available properties are:
     * <ul>
     *     <li>{@code coalescent.builder.RecursionComputers.exactProb = true | false}</li>
     *     <li>{@code coalescent.builder.RecursionComputers.configCounter = true | false}</li>
     *     <li>{@code coalescent.builder.RecursionComputers.genealogyCounter = true | false}</li>
     *     <li>{@code coalescent.builder.RecursionComputers.configBuilder = true | false}</li>
     *     <li>{@code coalescent.builder.RecursionComputers.genealogyBuilder = true | false}</li>
     *     <li>{@code coalescent.builder.RecursionComputers.fcChecker = true | false}</li>
     * </ul>
     *
     *
     * @param props properties object containing builder properties
     * @param prefix
     * @return a new builder instance for {@code List<RecursionListener>}
     */
    public static Builder<List<RecursionListener>> of_RecursionListeners(final Properties props,
            String prefix) {

        if (prefix == null) prefix = "coalescent.builder.RecursionComputers";

        return new RecursionComputationsBuilder.DEFAULT(prefix, props);
    }

    private Builders_Coa() {}

    /**
     * Builder with same properties as {@link #of_AC_KC64(java.util.Properties, String)}.
     */
    public static class AC_KC64 extends Builder.Delegate<KC64_AC> {

        public AC_KC64(final String prefix, final Properties props) {

            super(of_AC_KC64(props, prefix));

            setPrefix(prefix);
        }
    }

    /**
     * Builder with same properties as {@link #of_AC_K69_GT_File}.
     */
    public static final class AC_K69_GT_File extends Builder.Delegate<K69_AC> {

        public AC_K69_GT_File(final String prefix, final Properties props) {

            super(of_AC_K69_GT_File(props, null));

            setPrefix(prefix);
        }
    }

    /**
     * Builder with same properties as {@link #of_Data_KC64_K69Data(java.util.Properties, String)}.
     */
    public static class Data_KC64_K69Data extends Builder.Delegate<KC64Data.DEFAULT> {

        public Data_KC64_K69Data(final String prefix, final Properties props) {

            super(of_Data_KC64_K69Data(props, null));

            setPrefix(prefix);
        }
    }

    /**
     * Builder with same properties as {@link #of_Data_K69_File}.
     */
    public static final class Data_K69_File extends Builder.Delegate<K69Data> {

        public Data_K69_File(final String prefix, final Properties props) {

            super(of_Data_K69_File(props, null));

            setPrefix(prefix);
        }
    }

    /**
     * Builder with same properties as {@link #of_MetaInf_Mngr_K69Data_File}.
     */
    public static final class MetaInfMngr_K69Data_File
            extends Builder.Delegate<MetaInf_Mngr<MetaInf_K69Data>> {

        public MetaInfMngr_K69Data_File(final String prefix, final Properties props) {
            super(of_MetaInf_Mngr_K69Data_File(props, prefix, "coalescent.MetaInf"));
        }
    }

    /**
     * Builder with same properties as {@link #of_Model_K69(java.util.Properties, String)}.
     */
    public static final class Model_K69 extends Builder.Delegate<K69> {

        public Model_K69(final String prefix, final Properties props) {

            super(of_Model_K69(props, prefix));

            setPrefix(prefix);
        }
    }

    /**
     * Builder with same properties as {@link #of_Model_KC64(java.util.Properties, String)}.
     */
    public static final class Model_KC64 extends Builder.Delegate<KC64> {

        public Model_KC64(final String prefix, final Properties props) {

            super(of_Model_KC64(props, null));

            setPrefix(prefix);
        }
    }
}
